home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / internet / other / news / snz128s.tos / SRC / ACTIVE.C next >
Encoding:
C/C++ Source or Header  |  1994-07-28  |  31.3 KB  |  1,202 lines

  1. /*
  2.     SNEWS 2.0
  3.  
  4.     active.c - routines to manipulate the active and ng files
  5.  
  6.  
  7.     Copyright (C) 1991  John McCombs, Christchurch, NEW ZEALAND
  8.                         john@ahuriri.gen.nz
  9.                         PO Box 2708, Christchurch, NEW ZEALAND
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License, version 1, as
  13.     published by the Free Software Foundation.
  14.  
  15.     This program is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU General Public License for more details.
  19.  
  20.     See the file COPYING, which contains a copy of the GNU General
  21.     Public License.
  22.  
  23.     Atari Version maintained by Graham Judd - gjudd@siward.demon.co.uk
  24. */
  25.  
  26. /*---------------------------- Source Control ------------------------------*/
  27.  
  28. /* $Id: ACTIVE.C,v 1.2 1994/02/05 18:46:56 gbj Exp user $
  29.  
  30. /****************************************************************************
  31. *   20 May 92   1.2     GT  ka9q configuration.                             *
  32. *   06 Jun 92   1.3     GT  Invalidate freed pointers.                      *
  33. *   07 Jun 92   1.4     GT  Fix mailqueue parameter.                        *
  34. *   12 Jun 92   1.5     NJL Configurable quote marks & Bios video parm.     *
  35. *                           Ensure strtok() accepts tab as well as space.   *
  36. *   15 Jun 92   1.6     GT  Print name of file in error message.            *
  37. *   17 Jul 92   1.7     GT  C++ compilation.                                *
  38. *                           Heap debugging.                                 *
  39. *                           "junk" flag.                                    *
  40. *   16 Aug 92   1.8    MSM  Snews 1.90                                      *
  41. *                           Mail_dir added for 1.90 thread / item saving    *
  42. *                           Pseudo mail ID's added for article post / save  *
  43. *   10 Oct 92   1.9    MSM  Correct assumption that news == snews           *
  44. *   13 Feb 93   1.10   MSM  Add local posting option                        *
  45. *   20 Feb 93   1.11   MSM  Local Posting read option                       *
  46. *   31 May 93   1.12   MSM  Snews 2.0                                       *
  47. *                           temp_dir changed to be path only                *
  48. *                           ng made optional                                *
  49. *   18 Jun 93   1.13   MSM  Heap debugging removed (using Bounds Check)     *
  50. *    3 Jul 93   1.14   MSM  New UUCP items added for mail/editor            *
  51. *    1 Aug 93   1.15   MSM  Confirm Snews exit to DOS                       *
  52. *   11 Sep 93   1.16   MSM  Null extracts string corrected                  *
  53. *   25 Nov 93   1.17   MSM  Correct read list processing                    *
  54. *    4 Dec 93   1.18   MSM  Allow blank organisation and remove from reqd.  *
  55. *    2 Apr 94   1.19   MSM  Colour processing now ignores incomplete lines  *
  56. *                Footer support                    *
  57. *                Suspend support                    *
  58. ****************************************************************************/
  59.  
  60. #include <ctype.h>
  61. #include <fcntl.h>
  62. #include <io.h>
  63. #include "defs.h"
  64. #include "active.h"
  65. #include "screen.h"
  66. #include "locking.h"
  67.  
  68. #ifdef ATARI
  69. #    include "st.h"
  70. #    include "fileops.h"
  71. #endif
  72.  
  73. #ifndef __TURBOC__
  74. #    ifndef ATARI
  75. enum COLORS {
  76.     BLACK,          /* dark colors */
  77.     BLUE,
  78.     GREEN,
  79.     CYAN,
  80.     RED,
  81.     MAGENTA,
  82.     BROWN,
  83.     LIGHTGRAY,
  84.     DARKGRAY,       /* light colors */
  85.     LIGHTBLUE,
  86.     LIGHTGREEN,
  87.     LIGHTCYAN,
  88.     LIGHTRED,
  89.     LIGHTMAGENTA,
  90.     YELLOW,
  91.     WHITE
  92. };
  93. #    endif
  94. #endif
  95.  
  96. int             headf = BLACK;
  97. int             headb = LIGHTGRAY;
  98.  
  99. int             textf = LIGHTGRAY;
  100. int             textb = BLACK;
  101.  
  102. int             helpf = LIGHTGRAY;
  103. int             helpb = BLACK;
  104.  
  105. int             msgf = BLACK;
  106. int             msgb = LIGHTGRAY;
  107.  
  108.  
  109. /*
  110.  *    These private variables are used to do all the i/o on the active
  111.  *    file.
  112.  */
  113.  
  114. static FILE    *active_file;
  115. static ACTIVE  *local_head;
  116. static POST_GROUPS *pg;
  117.  
  118. /*-------------------------- load the active file --------------------------*/
  119.  
  120. ACTIVE         *load_active_file(void)
  121. {
  122.  
  123.     /*
  124.      * This routine opens the active file.
  125.      * It reads the data, allocating ACTIVE elements in a linked list.
  126.      * Returns a pointer to the head of the linked list.
  127.      */
  128.  
  129.     char            fn[80], buf[81];
  130.     char           *p;
  131.     ACTIVE         *this_act, *head = NULL;
  132.     long            posn = 0;
  133.     int             ct = 0;
  134.     int             ct_gp = 0;
  135.  
  136.     /* open the file */
  137.     strcpy(fn, my_stuff.news_dir);
  138.     strcat(fn, "active");
  139.     if ((active_file = fopen(fn, "r+b")) == NULL) {
  140.         fprintf(stderr, "cannot open %s\n", fn);
  141.         exit(1);
  142.     }
  143.     /* read and store */
  144.     while (fgets(buf, 80, active_file) != NULL) {
  145.  
  146.         /* exit on ^Z on column 1 */
  147.         if (buf[0] == '\x1A')
  148.             break;
  149.  
  150.         ct++;
  151.  
  152.         if (strlen(buf) > 0) {
  153.  
  154.             if (head == NULL) {
  155.                 head = this_act = (ACTIVE *) malloc(sizeof(ACTIVE));
  156.                 head->last = NULL;
  157.                 head->index = ct_gp;
  158.                 head->suspend = FALSE;
  159.             }
  160.             else {
  161.                 ct_gp++;
  162.                 this_act->next = (ACTIVE *) malloc(sizeof(ACTIVE));
  163.                 this_act->next->last = this_act;
  164.                 this_act = this_act->next;
  165.                 this_act->index = ct_gp;
  166.                 this_act->suspend = FALSE;
  167.             }
  168.  
  169.             if ((this_act) == NULL) {
  170.                 fprintf(stderr, "cannot allocate memory for active list\n");
  171.                 exit(1);
  172.             }
  173.             if ((p = strtok(buf, " \t")) == NULL) {
  174.                 fprintf(stderr, "active file corrupt at line %d\n", ct);
  175.                 exit(1);
  176.             }
  177.             strcpy(this_act->group, p);
  178.  
  179.             if ((p = strtok(NULL, " \t")) == NULL) {
  180.                 fprintf(stderr, "active file corrupt at line %d\n", ct);
  181.                 exit(1);
  182.             }
  183.             strcpy(this_act->gp_file, p);
  184.  
  185.             if ((p = strtok(NULL, " \t")) == NULL) {
  186.                 fprintf(stderr, "active file corrupt at line %d\n", ct);
  187.                 exit(1);
  188.             }
  189.             this_act->lo_num = atol(p);
  190.  
  191.             if ((p = strtok(NULL, " \t")) == NULL) {
  192.                 fprintf(stderr, "active file corrupt at line %d\n", ct);
  193.                 exit(1);
  194.             }
  195.             this_act->hi_num = atol(p);
  196.  
  197.             this_act->num_pos = posn;
  198.             this_act->read_list = NULL;
  199.         }
  200.         posn = ftell(active_file);
  201.     }
  202.  
  203.     this_act->next = NULL;
  204.     head->groups = ct;                      /* added for 2.0 */
  205.  
  206.     local_head = head;
  207.  
  208.     /* load up the posting list */
  209.     pg = post_group_file();
  210.  
  211.     return (head);
  212. }
  213.  
  214.  
  215. /*---------- free the active list and close the active file ----------------*/
  216. void            close_active_file(void)
  217. {
  218.  
  219.     /*
  220.      * Close the active file and deallocate the linked list
  221.      */
  222.  
  223.     ACTIVE         *this_act;
  224.  
  225.     this_act = local_head;
  226.  
  227.     while (this_act != NULL) {
  228.         local_head = this_act;
  229.         this_act = this_act->next;
  230.         free(local_head);
  231.         local_head = NULL;
  232.     }
  233.  
  234.     fclose(active_file);
  235.  
  236.     free_ng();
  237.  
  238. }
  239.  
  240.  
  241. /*------------------------- close the active file ---------------------------*/
  242. void            close_active(void)
  243. {
  244.  
  245.     /*
  246.      * Close the active file
  247.      */
  248.  
  249.  
  250.     fclose(active_file);
  251.  
  252. }
  253.  
  254.  
  255. /*--------------------------- load the newsgroups file --------------------------*/
  256. POST_GROUPS    *post_group_file(void)
  257. {
  258.  
  259.     /*
  260.      * This routine opens the active file.
  261.      * It reads the data, allocating POST_GROUPS elements in a linked list.
  262.      * Returns a pointer to the head of the linked list.
  263.      */
  264.  
  265.     char            fn[80], buf[81], *p;
  266.     POST_GROUPS    *this_group = NULL, *head = NULL;
  267.     int             ct = 0;
  268.     FILE           *ngf;
  269.  
  270.     /* open the file - if none, return null */
  271.     strcpy(fn, my_stuff.news_dir);
  272.     strcat(fn, "ng");
  273.     if ((ngf = fopen(fn, "rb")) == NULL) {
  274.         return (NULL);
  275.     }
  276.  
  277.     /* read and store */
  278.     while (fgets(buf, 80, ngf) != NULL) {
  279.  
  280.         /* exit on ^Z on column 1 */
  281.         if (buf[0] == '\x1A')
  282.             break;
  283.  
  284.         ct++;
  285.  
  286.         if (strlen(buf) > 0) {
  287.  
  288.             if (head == NULL) {
  289.                 head = this_group = (POST_GROUPS *) malloc(sizeof(POST_GROUPS));
  290.             }
  291.             else {
  292.                 this_group->next = (POST_GROUPS *) malloc(sizeof(POST_GROUPS));
  293.                 this_group = this_group->next;
  294.             }
  295.  
  296.             if ((this_group) == NULL) {
  297.                 fprintf(stderr, "cannot allocate memory for newsgroup list\n");
  298.                 exit(1);
  299.             }
  300.  
  301.             if ((p = strtok(buf, " \n\r\t")) == NULL) {
  302.                 fprintf(stderr, "newsgroup 'ng' file corrupt at line %d\n", ct);
  303.                 exit(1);
  304.             }
  305.  
  306.             strcpy(this_group->group, p);
  307.         }
  308.     }
  309.  
  310.     if (this_group)                          /* added in 2.0 */
  311.         this_group->next = NULL;
  312.  
  313.     fclose(ngf);
  314.  
  315.     return (head);
  316. }
  317.  
  318. /*-------------------- free the post groups structure ----------------------*/
  319. void            free_ng()
  320. {
  321.  
  322.     /*
  323.      * deallocate the post_groups linked list
  324.      */
  325.  
  326.     POST_GROUPS    *this_group;
  327.  
  328.     this_group = pg;
  329.  
  330.     while (this_group != NULL) {
  331.         pg = this_group;
  332.         this_group = this_group->next;
  333.         free(pg);
  334.         pg = NULL;
  335.     }
  336. }
  337.  
  338. /*------------------------- check group in post list -------------------------*/
  339. int             check_valid_post_group(char *ng)
  340. {
  341.  
  342.     /*
  343.      * Check a string as a valid newsgroup name.  Returns TRUE if found
  344.      */
  345.  
  346.     POST_GROUPS    *this_group;
  347.  
  348.     if (pg == NULL)
  349.         return (TRUE);                    /* no ng file, so default allow */
  350.  
  351.     this_group = pg;
  352.  
  353.     while (this_group != NULL) {
  354.         if (strcmp(ng, this_group->group) == 0)
  355.             return (TRUE);
  356.         this_group = this_group->next;
  357.     }
  358.  
  359.     return (FALSE);
  360. }
  361.  
  362. int             is_local_group(char *ng)
  363. {                                          /* added for 2.0 */
  364.     POST_GROUPS    *this_group;
  365.  
  366.     this_group = pg;
  367.  
  368.     while (this_group != NULL) {
  369.         if (strcmp(ng, this_group->group) == 0)
  370.             return (this_group->local);
  371.         this_group = this_group->next;
  372.     }
  373.     return (TRUE);
  374. }
  375.  
  376.  
  377. /*-------------------- find a newsgroup in active list ----------------------*/
  378. ACTIVE         *find_news_group(char *group, int *junk_flag)
  379. {
  380.  
  381.     /*
  382.      * This routine searches the active structure for the specified newsgroup,
  383.      * and returns a pointer to the entry, or to group junk if not found.
  384.      * The search for junk is made via a recursive call.
  385.      * Fatal if junk not found
  386.      */
  387.  
  388.     ACTIVE         *this_act;
  389. #ifdef ATARI
  390.     int done;
  391. #endif
  392.  
  393.     this_act = local_head;
  394.  
  395. #ifdef ATARI
  396.     done=FALSE;
  397.     while (!done)
  398.     {
  399.         if (this_act != NULL)
  400.             if (stricmp(group, this_act->group) != 0)
  401.             {
  402.                 done=FALSE;
  403.                 this_act=this_act->next;
  404.             }
  405.             else
  406.                 done=TRUE;
  407.         else
  408.             done=TRUE;
  409.     }
  410. #else
  411.     while ((this_act != NULL) && (stricmp(group, this_act->group) != 0)) {
  412.         this_act = this_act->next;
  413.     }
  414. #endif
  415.  
  416.     *junk_flag = 0;
  417.     if (this_act == NULL) {
  418.         if (stricmp(group, "junk") != 0) {
  419.             this_act = find_news_group("junk", junk_flag);
  420.             *junk_flag = 1;
  421.         }
  422.         else {
  423.             fprintf(stderr, "active file must have newsgroup junk\n");
  424.             exit(1);
  425.         }
  426.     }
  427.     return (this_act);
  428.  
  429. }
  430.  
  431.  
  432. /*-------------------------- update active file ---------------------------*/
  433. void            update_active_entry(ACTIVE * a)
  434. {
  435.  
  436.     /*
  437.      * This routine takes a pointer to an active entry and updates its data
  438.      * on disk
  439.      */
  440.  
  441.     char            buf[(ACTIVE_NUM_LEN * 2) + 2];
  442.     int             n;
  443.     long            where;
  444.  
  445.     sprintf(buf, "%08ld %08ld", a->lo_num, a->hi_num);
  446.  
  447.     n = (ACTIVE_NUM_LEN * 2) + 1;
  448.     where = a->num_pos + strlen(a->group) + 1 + strlen(a->gp_file) + 1;
  449.     fseek(active_file, where, SEEK_SET);
  450.     if (fwrite(buf, 1, n, active_file) != (unsigned)n) {
  451.         fprintf(stderr, "active file update failed for %s\n", a->group);
  452.         exit(1);
  453.     }
  454.     fflush(active_file);
  455. }
  456.  
  457. /*------------------- make newsgroup name and directory --------------------*/
  458. char           *make_news_group_name(char *ng)
  459. {
  460.  
  461.     /*
  462.      * This routine takes the newsgroup name, replaces the '.' with '\'
  463.      * and creates the directory if none exists.  The returned name
  464.      * has a trailing '\'.
  465.      * It doesn't do this for the DOS/ATARI version!
  466.      */
  467.  
  468.     static char     fn[80];               /* was 512 DOS name is 64 max */
  469.     ACTIVE         *tmp;
  470.     int             junk_flag;
  471.  
  472.     tmp = find_news_group(ng, &junk_flag);
  473.  
  474.     sprintf(fn, "%snewsbase\\%s", my_stuff.news_dir, tmp->gp_file);
  475.  
  476.     return (&fn[0]);
  477. }
  478.  
  479.  
  480. /*-------------------------- load the seen list -------------------------*/
  481. void            load_read_list(void)
  482. {
  483.  
  484.     /*
  485.      * Load the user's list of seen articles
  486.      */
  487.  
  488.     FILE           *tmp_file;
  489.     ACTIVE         *act;
  490.     int             i, continue_flag;
  491.     int             articles;
  492.     char           *a, buf[256], *p, real_name[80];
  493.     int             junk_flag;
  494.  
  495.     /* allocate the arrays and set to unread, ie FALSE */
  496.     act = local_head;
  497.     while (act != NULL) {
  498.  
  499.         articles = (int) (act->hi_num - act->lo_num);
  500.         if (articles > 0) {
  501.             a = act->read_list = (char *) malloc(articles * sizeof(char));
  502.             for (i = 0; i < articles; i++) {
  503.                 *(a + i) = FALSE;
  504.             }
  505.         }
  506.         else {
  507.             act->read_list = NULL;
  508.         }
  509.         act = act->next;
  510.     }
  511.  
  512.     /* read and process the file - if not present, just carry on */
  513.  
  514.     strcpy(buf, my_stuff.news_dir);
  515.     strcat(buf, my_stuff.user);
  516.     strcat(buf, ".nrc");
  517.     if ((tmp_file = fopen(buf, "rt")) != NULL) {
  518.  
  519.         continue_flag = FALSE;
  520.         while (fgets(buf, 255, tmp_file) != NULL) {
  521.  
  522.             p = strtok(buf, " \t\n\r");
  523.  
  524.             if (!continue_flag) {
  525.  
  526.                 strcpy(real_name, p);
  527.                 act = find_news_group(p, &junk_flag);
  528.                 articles = (int) (act->hi_num - act->lo_num);
  529.  
  530.                 /* if no articles or unknown group eat the rest */
  531.  
  532.                 p = strtok(NULL, " \t\n\r");
  533.  
  534.             }
  535.  
  536.             /* scan the rest of the line getting numbers and setting flags */
  537.  
  538.             continue_flag = FALSE;
  539.             while (p != NULL) {
  540.  
  541.                 /* check for continuation backslash */
  542.  
  543.                 if (*p != '\\') {
  544.                     i = (int) (atol(p) - (act->lo_num + 1));
  545.                     if ((i >= 0) && (i < articles) &&
  546.                         ((stricmp(act->group, "junk") != 0) ||
  547.                          (stricmp(real_name, "junk") == 0))) {
  548.                         *((act->read_list) + i) = (char) TRUE;
  549.                     }
  550.                 }
  551.                 else {
  552.                     continue_flag = TRUE;
  553.                     break;
  554.                 }
  555.                 p = strtok(NULL, " \t\n\r");
  556.             }
  557.         }
  558.  
  559.         fclose(tmp_file);
  560.     }
  561. }
  562.  
  563. /*-------------------------- save the seen list -------------------------*/
  564. void            save_read_list(void)
  565. {
  566.  
  567.     /*
  568.      * Save the user's list of read articles and deallocate storage
  569.      */
  570.  
  571.  
  572.     FILE           *tmp_file;
  573.     ACTIVE         *act;
  574.     int             i, articles, ct;
  575.     char            buf[256];
  576.  
  577.     /* open the file */
  578.     strcpy(buf, my_stuff.news_dir);
  579.     strcat(buf, my_stuff.user);
  580.     strcat(buf, ".nrc");
  581.     if ((tmp_file = fopen(buf, "wt")) == NULL) {
  582.         fprintf(stderr, "can't open user's rc file \"%s\" for output\n", buf);
  583.         exit(1);
  584.     }
  585.  
  586.     /* write out the lists and deallocate the arrays */
  587.  
  588.     act = local_head;
  589.     while (act != NULL) {
  590.  
  591.         articles = (int) (act->hi_num - act->lo_num);
  592.         if (articles > 0) {
  593.             fprintf(tmp_file, "%s ", act->group);
  594.  
  595.             ct = 0;
  596.  
  597.             for (i = 0; i < articles; i++) {
  598.                 if (*((act->read_list) + i)) {
  599.                     ct++;
  600.                     fprintf(tmp_file, "%d ", i + act->lo_num + 1);
  601.                     if ((ct % 10) == 0)
  602.                         fprintf(tmp_file, "\\ \n");
  603.                 }
  604.             }
  605.  
  606.             fprintf(tmp_file, "\n");
  607.             if (act->read_list != NULL) {
  608.                 free(act->read_list);
  609.                 act->read_list = NULL;
  610.             }
  611.         }
  612.         act = act->next;
  613.     }
  614.  
  615.     fclose(tmp_file);
  616.  
  617. }
  618.  
  619. /*------------------------- set colors -----------------------------------*/
  620.  
  621. void            set_colors(char *keyword, char *value)
  622. {
  623.     static char    *colors[] = {"bla", "blu", "gre", "cya", "red", "mag", "yel", "whi"};
  624.     int             color = 0, i = 0;
  625.     char           *f = NULL;
  626.  
  627.     if (value)
  628.         strlwr(value);
  629.  
  630.     f = strtok(value, "\0");
  631.  
  632.     while (isspace(*f))
  633.         f++;
  634.  
  635.     for (i = 0; (i < 8) && (strncmp(colors[i], f, 3) != 0); i++)
  636.          /* empty loop */ ;
  637.  
  638.     color = (i < 8) ? i : 0;
  639.     color |= (strchr(f, '+') != NULL) ? 8 : 0;
  640.  
  641.     helpf = (strncmp("helpf", keyword, 5)) ? helpf : (unsigned char) color;
  642.     helpb = (strncmp("helpb", keyword, 5)) ? helpb : (unsigned char) color;
  643.  
  644.     textf = (strncmp("textf", keyword, 5)) ? textf : (unsigned char) color;
  645.     textb = (strncmp("textb", keyword, 5)) ? textb : (unsigned char) color;
  646.  
  647.     headf = (strncmp("headf", keyword, 5)) ? headf : (unsigned char) color;
  648.     headb = (strncmp("headb", keyword, 5)) ? headb : (unsigned char) color;
  649.  
  650.     msgf = (strncmp("msgf", keyword, 4)) ? msgf : (unsigned char) color;
  651.     msgb = (strncmp("msgb", keyword, 4)) ? msgb : (unsigned char) color;
  652. }
  653.  
  654. /*------------------------- load UUPC rc files ---------------------------*/
  655. int             load_stuff(void)
  656. {
  657.  
  658.     /*
  659.      * Trawl the UUPC files to get the stuff we need
  660.      *    - return TRUE if completed ok
  661.      */
  662.  
  663.     int             i, res = 0;
  664.     char            buf[256], buf2[80];
  665.     char           *fn, *p, *v, *q;
  666.     FILE           *tmp;
  667.  
  668.     /* news base directory */
  669.  
  670.     if ((fn = getenv("SNEWS")) == NULL) {
  671.         (void) fprintf(stderr, "SNEWS environment variable undefined\n");
  672.         exit(1);
  673.     }
  674.  
  675.     /* give it a trailing \ */
  676.  
  677.     (void) strcpy(my_stuff.news_dir, fn);
  678.     if (my_stuff.news_dir[strlen(my_stuff.news_dir) - 1] != '\\')
  679.         (void) strcat(my_stuff.news_dir, "\\");
  680.  
  681.     /* Set up default items where appropriate */
  682.  
  683.     (void) strcpy(my_stuff.quotemark, ">");
  684.     my_stuff.directvideo = 1;              /* default to direct video */
  685.     my_stuff.localpost = 0;                  /* default to posting via demon */
  686.     my_stuff.localread = 0;                  /* default to reading local posts */
  687.     my_stuff.exitconfirm = 1;             /* default, don't ask */
  688.     my_stuff.expert = FALSE;              /* default to non expert */
  689.     strcpy(my_stuff.replyuser, "");          /* default no replyto name */
  690.     strcpy(my_stuff.mailuser, "newspost");/* default posting log  */
  691.     strcpy(my_stuff.maillog, "outmail");  /* default mail log */
  692.     strcpy(my_stuff.extruser, "snewsex"); /* default extract file */
  693.     strcpy(my_stuff.my_organisation, ""); /* default organisation */
  694.     strcpy(my_stuff.mail_id, "mail2news");/* default mail to news ID */
  695.     strcpy(my_stuff.edit_line, "");       /* default editor command */
  696.     strcpy(my_stuff.alias_file, "");      /* default alias file */
  697.     my_stuff.tab_action = TRUE;           /* New tab action by default */
  698.     my_stuff.header_quote = FALSE;        /* No header quotes by default */
  699.     my_stuff.footer_quote = TRUE;          /* Footer quotes on by default */
  700.     my_stuff.show_unread = TRUE;          /* Show unread threads etc. */
  701.     my_stuff.match_len = 15;              /* Length of header minimum match */
  702.  
  703.     /* read the system file first */
  704.  
  705.     (void) strcpy(buf, my_stuff.news_dir);
  706.     (void) strcat(buf, "snews.rc");
  707.     if ((tmp = fopen(buf, "rt")) != NULL) {
  708.         while (fgets(buf, 255, tmp)) {
  709.             p = strtok(buf, " \t=\r\n");
  710.             if (p != NULL) {
  711.                 if (*p != '#') {
  712.                     v = strtok(NULL, " \t=\r\n");
  713.                     if ((stricmp(p, "newsserver") == 0) && (v != NULL)) {
  714.                         (void) strcpy(my_stuff.mail_server, v);
  715.                         res++;
  716.                     }
  717.  
  718.                     if ((stricmp(p, "colour") == 0) && (v != NULL)) {
  719.                         p = strtok(NULL, " \r\n");
  720.                         set_colors(v, p);
  721.                     }
  722.  
  723.                     if ((stricmp(p, "nodename") == 0) && (v != NULL)) {
  724.                         (void) strcpy(my_stuff.my_site, v);
  725.                         res++;
  726.                     }
  727.  
  728.                     if ((stricmp(p, "newsdir") == 0) && (v != NULL)) {
  729.                         (void) strcpy(my_stuff.incoming_dir, v);
  730.                         if (my_stuff.incoming_dir[strlen(my_stuff.incoming_dir) - 1] != '\\')
  731.                             (void) strcat(my_stuff.incoming_dir, "\\");
  732.                         res++;
  733.                     }
  734.  
  735.                     if ((stricmp(p, "domain") == 0) && (v != NULL)) {
  736.                         (void) strcpy(my_stuff.my_domain, v);
  737.                         res++;
  738.                     }
  739.  
  740.                     if ((stricmp(p, "tempdir") == 0) && (v != NULL)) {
  741.                         (void) strcpy(my_stuff.temp_name, v);
  742.                         if (my_stuff.temp_name[strlen(my_stuff.temp_name)-1] == '\\')
  743.                             my_stuff.temp_name[strlen(my_stuff.temp_name)-1] = '\0';
  744.                         res++;
  745.                     }
  746.  
  747.                     if ((stricmp(p, "aliasfile") == 0) && (v != NULL)) {
  748.                         strcpy(my_stuff.alias_file, v);
  749.                       /* not a required item */
  750.                     }
  751.  
  752.                     if ((stricmp(p, "userid") == 0) && (v != NULL)) {
  753.                         (void) strcpy(my_stuff.user, v);
  754.                         res++;
  755.                     }
  756.  
  757.                     if ((stricmp(p, "Signature") == 0) && (v != NULL)) {
  758.                         (void) strcpy(my_stuff.signature, v);
  759.                         res++;
  760.                     }
  761.  
  762.                     if ((stricmp(p, "name") == 0) && (v != NULL)) {
  763.                         (void) strcpy(my_stuff.my_name, v);
  764.                         v = strtok(NULL, " \t=\r\n");
  765.                         while (v != NULL) {
  766.                             (void) strcat(my_stuff.my_name, " ");
  767.                             (void) strcat(my_stuff.my_name, v);
  768.                             v = strtok(NULL, " \t=\r\n");
  769.                         }
  770.                         if (strpbrk(my_stuff.my_name, "()<>@.;:\\\".[]") != NULL) {
  771.                             strcpy(buf2, my_stuff.my_name);
  772.                             strcpy(my_stuff.my_name, "\"");
  773.                             strcat(my_stuff.my_name, buf2);
  774.                             strcat(my_stuff.my_name, "\"");
  775.                         }
  776.                         res++;
  777.                     }
  778.  
  779.                     if ((stricmp(p, "Organization") == 0) && (v != NULL)) {
  780.                         (void) strcpy(my_stuff.my_organisation, v);
  781.                         v = strtok(NULL, " \t=\r\n");
  782.                         while (v != NULL) {
  783.                             (void) strcat(my_stuff.my_organisation, " ");
  784.                             (void) strcat(my_stuff.my_organisation, v);
  785.                             v = strtok(NULL, " \t=\r\n");
  786.                         }
  787.                         /* Organisation no longer compulsory */
  788.                     }
  789.  
  790.                     if ((stricmp(p, "Replyto") == 0) && (v != NULL)) {
  791.                         (void) strcpy(my_stuff.replyuser, v);
  792.                         v = strtok(NULL, " =\r\n");
  793.                         while (v != NULL) {
  794.                             (void) strcat(my_stuff.replyuser, " ");
  795.                             (void) strcat(my_stuff.replyuser, v);
  796.                             v = strtok(NULL, " =\r\n");
  797.                         }
  798.                     }                        /* not a required item for DIS. Don't bump res */
  799.  
  800.                     if ((stricmp(p, "Editor") == 0) && (v != NULL)) {
  801.                         (void) strcpy(my_stuff.editor, v);
  802.                         res++;
  803.                         v = strtok(NULL, " \t=\r\n");
  804.                         while (v != NULL) {
  805.                             (void) strcat(my_stuff.editor, " ");
  806.                             (void) strcat(my_stuff.editor, v);
  807.                             v = strtok(NULL, " \t=\r\n");
  808.                         }
  809.                         strlwr(my_stuff.editor);
  810.  
  811.                     }
  812.  
  813.                     if ((stricmp(p, "Editline") == 0) & (v != NULL)) {
  814.                         (void) strcpy(my_stuff.edit_line, v);
  815.                         v = strtok(NULL, " \r\n");
  816.                         while (v != NULL) {
  817.                             strcat(my_stuff.edit_line, " ");
  818.                             strcat(my_stuff.edit_line, v);
  819.                             v = strtok(NULL, " \r\n");
  820.                         }
  821.                     }
  822.  
  823.                     if ((stricmp(p, "Home") == 0) && (v != NULL)) {
  824.                         (void) strcpy(my_stuff.home, v);
  825.                         if (my_stuff.home[strlen(my_stuff.home) - 1] != '\\')
  826.                             (void) strcat(my_stuff.home, "\\");
  827.  
  828.                         res++;
  829.                     }
  830.  
  831.                     if ((stricmp(p, "mailqueue") == 0) && (v != NULL)) {
  832.                         (void) strcpy(my_stuff.spooldir, v);
  833.                         if (my_stuff.spooldir[strlen(my_stuff.spooldir) - 1] != '\\')
  834.                             (void) strcat(my_stuff.spooldir, "\\");
  835.  
  836.                         res++;
  837.                     }
  838.  
  839.                     if ((stricmp(p, "mailuser") == 0) && (v != NULL)) {
  840.                         if (v != NULL) {
  841.                             (void) strcpy(my_stuff.mailuser, v);
  842.                             if (strlen(my_stuff.mailuser) > 8)
  843.                                 my_stuff.mailuser[8] = '\0';
  844.                             i = strlen(my_stuff.mailuser) - 1;
  845.                             if (my_stuff.mailuser[i] == '.')
  846.                                 my_stuff.mailuser[i] = '\0';
  847.                         }
  848.                         else
  849.                             strcpy(my_stuff.mailuser, "none");
  850.                     /* Mailuser is not a required item to maintain compatibility */
  851.                     }
  852.  
  853.                     if ((stricmp(p, "maillog") == 0) && (v != NULL)) {
  854.                         if (v != NULL) {
  855.                             (void) strcpy(my_stuff.maillog, v);
  856.                             if (strlen(my_stuff.maillog) > 8)
  857.                                 my_stuff.maillog[8] = '\0';
  858.                             i = strlen(my_stuff.maillog) - 1;
  859.                             if (my_stuff.maillog[i] == '.')
  860.                                 my_stuff.maillog[i] = '\0';
  861.                         }
  862.                         else
  863.                             strcpy(my_stuff.maillog, "none");
  864.                     /* Maillog is not a required item to maintain compatibility */
  865.                     }
  866.  
  867.                     if ((stricmp(p, "extracts") == 0) && (v != NULL)) {
  868.                         (void) strcpy(my_stuff.extruser, v);
  869.                         if (strlen(my_stuff.extruser) > 8)
  870.                             my_stuff.extruser[8] = '\0';
  871.                         i = strlen(my_stuff.extruser) - 1;
  872.                         if (my_stuff.extruser[i] == '.')
  873.                             my_stuff.extruser[i] = '\0';
  874.                     /* Extracts is not a required item to maintain compatibility */
  875.                     }
  876.  
  877.                     if ((stricmp(p, "quotemark") == 0) && (v != NULL)) {
  878.                         (void) strcpy(my_stuff.quotemark, v);
  879.                         q = my_stuff.quotemark;
  880.                         for(;*q != '\0';q++)
  881.                             if (*q == '_')
  882.                                 *q = ' ';
  883.                     /* Quotemark not a required item, so leave 'res' alone */
  884.                     }
  885.  
  886.                     if ((stricmp(p, "biosvideo") == 0) && (v != NULL)) {
  887.                         if (stricmp(v, "0") == 0
  888.                             || stricmp(v, "false") == 0
  889.                             || stricmp(v, "no") == 0
  890.                             || stricmp(v, "off") == 0)
  891.                             my_stuff.directvideo = 1;
  892.                         else if (stricmp(v, "2") == 0)
  893.                             my_stuff.directvideo = 2;
  894.                         else
  895.                             my_stuff.directvideo = 0;
  896.                     /* biosvideo not a required item, so leave 'res' alone */
  897.                     }
  898.  
  899.                     if ((stricmp(p, "matchlength") == 0) && (v != NULL)) {
  900.                         my_stuff.match_len = atoi(v);
  901.                         if (my_stuff.match_len > 128)
  902.                             my_stuff.match_len = 128;
  903.                         if (my_stuff.match_len < -1)
  904.                             my_stuff.match_len = -1;
  905.                     /* matchlength is not a required item. */
  906.                     }
  907.  
  908.                     if ((stricmp(p, "exitconfirm") == 0) && (v != NULL)) {
  909.                         if (stricmp(v, "0") == 0
  910.                             || stricmp(v, "false") == 0
  911.                             || stricmp(v, "no") == 0
  912.                             || stricmp(v, "off") == 0)
  913.                             my_stuff.exitconfirm = 1;
  914.                         else if (stricmp(v, "2") == 0)
  915.                             my_stuff.exitconfirm = 2;
  916.                         else
  917.                             my_stuff.exitconfirm = 0;
  918.                     /* exitconfirm not a required item, so leave 'res' alone */
  919.                     }
  920.  
  921.                     if ((stricmp(p, "expert") == 0) && (v != NULL)) {
  922.                         if (stricmp(v, "0") == 0
  923.                             || stricmp(v, "false") == 0
  924.                             || stricmp(v, "no") == 0
  925.                             || stricmp(v, "off") == 0)
  926.                             my_stuff.expert = FALSE;
  927.                         else
  928.                             my_stuff.expert = TRUE;
  929.                     /* expert not a required item, so leave 'res' alone */
  930.                     }
  931.  
  932.                     if ((stricmp(p, "TAB") == 0) && (v != NULL)) {
  933.                         if (stricmp(v, "0") == 0
  934.                             || stricmp(v, "false") == 0
  935.                             || stricmp(v, "no") == 0
  936.                             || stricmp(v, "off") == 0)
  937.                             my_stuff.tab_action = FALSE;
  938.                         else
  939.                             my_stuff.tab_action = TRUE;
  940.                     }
  941.  
  942.                     if ((stricmp(p, "HEADERS") == 0) && (v != NULL)) {
  943.                         if (stricmp(v, "0") == 0
  944.                             || stricmp(v, "false") == 0
  945.                             || stricmp(v, "no") == 0
  946.                             || stricmp(v, "off") == 0)
  947.                             my_stuff.header_quote = FALSE;
  948.                         else
  949.                             my_stuff.header_quote = TRUE;
  950.                     }
  951.  
  952.                     if ((stricmp(p, "FOOTERS") == 0) && (v != NULL)) {
  953.                         if (stricmp(v, "0") == 0
  954.                             || stricmp(v, "false") == 0
  955.                             || stricmp(v, "no") == 0
  956.                             || stricmp(v, "off") == 0)
  957.                             my_stuff.footer_quote = FALSE;
  958.                         else
  959.                             my_stuff.footer_quote = TRUE;
  960.                     }
  961.  
  962.                     if ((stricmp(p, "UNREAD") == 0) && (v != NULL)) {
  963.                         if (stricmp(v, "0") == 0
  964.                             || stricmp(v, "false") == 0
  965.                             || stricmp(v, "no") == 0
  966.                             || stricmp(v, "off") == 0)
  967.                             my_stuff.show_unread = FALSE;
  968.                         else
  969.                             my_stuff.show_unread = TRUE;
  970.                     }
  971.  
  972.                     if ((stricmp(p, "post") == 0) && (v != NULL)) {
  973.                         if (strnicmp(v, "local", 5) == 0)
  974.                             my_stuff.localpost = 1;
  975.                         else
  976.                             my_stuff.localpost = 0;
  977.                         if (stricmp(v, "local/read") == 0)
  978.                             my_stuff.localread = 1;
  979.                         else
  980.                             my_stuff.localread = 0;
  981.                     /* post is not a required item */
  982.                     }
  983.  
  984.                     if ((stricmp(p, "newsid") == 0) && (v != NULL)) {
  985.                         (void) strcpy(my_stuff.mail_id, v);
  986.                         /* newsid is not a required item */
  987.                     }
  988.                 }                         /* if (*p != '#') */
  989.             }                              /* if (p != NULL) */
  990.         }                                  /* while (fgets (buf, 255, tmp)) */
  991.  
  992.         fclose(tmp);
  993.         strcpy(my_stuff.mail_dir, my_stuff.spooldir);
  994.         p = strrchr(my_stuff.mail_dir, '\\');
  995.         if (p != NULL) {
  996.             *p = '\0';
  997.             p = strrchr(my_stuff.mail_dir, '\\');
  998.             *(p + 1) = '\0';
  999.         }
  1000.         strcpy(my_stuff.nntp_dir, my_stuff.mail_dir);
  1001.         strcat(my_stuff.mail_dir, "mail\\");
  1002.         strcat(my_stuff.nntp_dir, "news\\");
  1003.     }                                      /* if ((tmp = fopen (buf, "rt")) != NULL) */
  1004.     else {
  1005.         (void) fprintf(stderr, "Cannot open %s\n", buf);
  1006.     }
  1007.  
  1008.     return (res == 11);
  1009. }                                          /* int load_stuff (void) */
  1010.  
  1011.  
  1012. /*--------------------------- open newsgroup ------------------------*/
  1013. FILE           *open_out_file(char *ng, int *junk_flag)
  1014. {
  1015.  
  1016.     /*
  1017.      * This routine creates a filename from the newsgroup name. 
  1018.      * The active file counters are updated.
  1019.      */
  1020.  
  1021.     ACTIVE         *gp;
  1022.     char           *fn;
  1023.     FILE           *tmp;
  1024.  
  1025.     gp = find_news_group(ng, junk_flag);
  1026.     fn = make_news_group_name(gp->group);
  1027.  
  1028.     (gp->hi_num)++;
  1029.     update_active_entry(gp);
  1030.  
  1031.     if ((tmp = fopen(fn, "r+b")) == NULL) {
  1032.         fprintf(stderr, "active: cannot open text file %s\n", fn);
  1033.         exit(1);
  1034.     }
  1035.     fseek(tmp, 0, SEEK_END);
  1036.  
  1037.     return (tmp);
  1038.  
  1039. }
  1040.  
  1041.  
  1042. /*--------------------------- open index ------------------------*/
  1043. FILE           *open_index_file(char *ng)
  1044. {
  1045.  
  1046.     /*
  1047.      * This routine open the index file for the newsgroup
  1048.      */
  1049.  
  1050.     ACTIVE         *gp;
  1051.     char            fnx[256], *fn;
  1052.     FILE           *tmp;
  1053.     int             junk_flag;
  1054.  
  1055.     /* printf("news: ng found = %s\n", ng); */
  1056.  
  1057.     gp = find_news_group(ng, &junk_flag);
  1058.     fn = make_news_group_name(gp->group);
  1059.     sprintf(fnx, "%s.IDX", fn);
  1060.  
  1061.     if ((tmp = fopen(fnx, "r+b")) == NULL) {
  1062.         fprintf(stderr, "active: cannot open index file %s\n", fn);
  1063.         exit(1);
  1064.     }
  1065.     fseek(tmp, 0, SEEK_END);
  1066.  
  1067.     return (tmp);
  1068.  
  1069. }
  1070.  
  1071. /*------------------------ Load suspend list --------------------------------*/
  1072. SUSPEND        *load_suspend(void)
  1073. {
  1074.     char    fn[80], buf[256];
  1075.     FILE    *suspend_file;
  1076.     SUSPEND    *suspend_head, *sus;
  1077.  
  1078.     /* open the file */
  1079.     strcpy(fn, my_stuff.news_dir);
  1080.     strcat(fn, "suspend");
  1081.     if ((suspend_file = fopen(fn, "r+b")) == NULL) {
  1082.         return NULL;
  1083.     }
  1084.     suspend_head = sus = NULL;
  1085.     /* read and store */
  1086.     while (fgets(buf, 80, suspend_file) != NULL) {
  1087.  
  1088.         /* exit on ^Z on column 1 */
  1089.         if (buf[0] == '\x1A')
  1090.             break;
  1091.         while ((buf[strlen(buf)-1] == '\n') || (buf[strlen(buf)-1] == '\r'))
  1092.             buf[strlen(buf)-1] = '\0';
  1093.  
  1094.         if (strlen(buf) > 0) {
  1095.             if (sus == NULL) {
  1096.                 sus = (SUSPEND*)malloc(sizeof(SUSPEND));
  1097.                 strcpy(sus->group, buf);
  1098.                 sus->next = NULL;
  1099.                 suspend_head = sus;
  1100.             }
  1101.             else {
  1102.                 sus->next = (SUSPEND*)malloc(sizeof(SUSPEND));
  1103.                 sus = sus->next;
  1104.                 sus->next = NULL;
  1105.                 strcpy(sus->group, buf);
  1106.             }
  1107.         }
  1108.     }
  1109.     return suspend_head;
  1110. }
  1111.  
  1112. /*------------------------- Add suspend info -------------------------------*/
  1113. void        add_suspend(ACTIVE *head)
  1114. {
  1115.     SUSPEND    *suspend_head, *sus;
  1116.     ACTIVE    *act;
  1117.  
  1118.     suspend_head = load_suspend();
  1119.     act = head;
  1120.     if (suspend_head == NULL)
  1121.         return;
  1122.  
  1123.     while (act != NULL) {
  1124.         sus = suspend_head;
  1125.         while (sus != NULL) {
  1126.             if (stricmp(sus->group, act->group) == 0)
  1127.                 act->suspend = TRUE;
  1128.             sus = sus->next;
  1129.         }
  1130.         act = act->next;
  1131.     }
  1132.  
  1133.     free_suspend(suspend_head);
  1134. }
  1135.  
  1136. /*------------------------- Free suspend structure -------------------------*/
  1137. void        free_suspend(SUSPEND *suspend_head)
  1138. {
  1139.     SUSPEND *sus, *sus2;
  1140.  
  1141.     sus = suspend_head;
  1142.  
  1143.     while (sus != NULL) {
  1144.         sus2 = sus->next;
  1145.         free(sus);
  1146.         sus = sus2;
  1147.     }
  1148. }
  1149.  
  1150. /*------------------------- post sequence number ----------------------------*/
  1151. int             post_sequence(void)
  1152. {
  1153.  
  1154.     /*
  1155.      * Get the sequnce number from the seq file if it exists
  1156.      *    - if not create it
  1157.      */
  1158.  
  1159.     FILE           *seq_file;
  1160.     char            fn[256];
  1161.     int             seq;
  1162.  
  1163.     strcpy(fn, my_stuff.news_dir);
  1164.     strcat(fn, "nseq");
  1165.  
  1166.     if (mlock(my_stuff.news_dir, "nseq", "Active") != 0)
  1167.         return -1;
  1168.     if ((seq_file = fopen(fn, "r+")) != NULL) {
  1169.         fscanf(seq_file, "%d", &seq);
  1170.         seq++;
  1171.         rewind(seq_file);
  1172.     }
  1173.     else {
  1174.         seq = 0;
  1175.         seq_file = fopen(fn, "wt");
  1176.     }
  1177.  
  1178.     fprintf(seq_file, "%d", seq);
  1179.  
  1180.     fclose(seq_file);
  1181.     rmlock(my_stuff.news_dir, "nseq", "Active");
  1182.     return (seq);
  1183. }
  1184.  
  1185.  
  1186. /*-------------------------------- safeish malloc --------------------------*/
  1187. #if defined (malloc)
  1188. #undef    malloc
  1189. #endif
  1190.  
  1191. void           *xmalloc(size_t size)
  1192. {
  1193.     void           *p;
  1194.  
  1195.     if ((p = malloc(size)) == NULL) {
  1196.         gotoxy(1, 25);
  1197.         fprintf(stderr, "\n\nSORRY - OUT OF MEMORY \n");
  1198.         exit(1);
  1199.     }
  1200.     return (p);
  1201. }
  1202.